package com.sicau.smarttraceplatform.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sicau.smarttraceplatform.common.aop.ValidateAspect;
import com.sicau.smarttraceplatform.common.returning.ResultData;
import com.sicau.smarttraceplatform.entity.User;
import com.sicau.smarttraceplatform.entity.param.user.UserAddParam;
import com.sicau.smarttraceplatform.entity.param.user.UserQueryParam;
import com.sicau.smarttraceplatform.entity.param.user.UserUpdateParam;
import com.sicau.smarttraceplatform.entity.vo.PageDataVO;
import com.sicau.smarttraceplatform.entity.vo.user.UserVO;
import com.sicau.smarttraceplatform.service.UserService;
import com.sicau.smarttraceplatform.utils.MD5Util;
import com.sicau.smarttraceplatform.utils.UUIDUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.dozer.Mapper;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime;

import static com.sicau.smarttraceplatform.common.constants.CommonURLConstants.USER_PREFIX;
import static com.sicau.smarttraceplatform.common.constants.commonConstants.CURRENT_USER;

/**
 * <p>
 * 用户 前端控制器
 * </p>
 *
 * @author sxt && ttxxi
 * @since 2020-05-24
 */
@RestController
@RequestMapping(USER_PREFIX)
@Slf4j
@Api(tags = "用户相关")
public class UserController {

    @Resource
    private UserService userService;
    @Resource
    private Mapper dozerMapper;


    @PostMapping
    @ApiOperation(value = "新增用户信息记录")
    @ValidateAspect.ParamValidate()
    public ResultData<Boolean> addTraceInfo(@ApiParam(hidden = true) HttpServletRequest request,
                                            @Valid UserAddParam userAddParam,
                                            @ApiParam(hidden = true) @SuppressWarnings("unused") BindingResult bindingResult) {

        //账号重复性判断
        int count = userService.count(new LambdaQueryWrapper<User>().eq(User::getAccount, userAddParam.getAccount()));
        if (count > 0) {
            log.info("用户信息添加失败, 账号信息已存在");
            return new ResultData<Boolean>()
                    .FAILED()
                    .setResultIns("用户信息添加失败, 账号信息已存在")
                    .setObj(Boolean.FALSE);
        }

        //数据整理
        User tmpUser = new User();
        BeanUtils.copyProperties(userAddParam, tmpUser);
        String salt = UUIDUtils.getCode();
        User user = (User) request.getSession().getAttribute(CURRENT_USER);
        tmpUser.setCreator(user != null ? user.getId().toString() : null)
                .setCreated(LocalDateTime.now())
                .setSalt(salt)
                .setPassword(MD5Util.encode(tmpUser.getPassword() + salt));


        log.info("新增用户信息记录操作, 溯源信息: {}", tmpUser);

        //添加操作
        boolean rs = userService.save(tmpUser);

        //结果返回
        if (rs) {
            log.info("用户信息添加成功");
            return new ResultData<Boolean>()
                    .OK()
                    .setResultIns("用户信息添加成功")
                    .setObj(Boolean.TRUE);
        } else {
            log.info("用户信息添加失败");
            return new ResultData<Boolean>()
                    .FAILED()
                    .setResultIns("用户信息添加失败")
                    .setObj(Boolean.FALSE);
        }

    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @GetMapping
    @ApiOperation(value = "查询用户信息(传入条件则根据条件查询, 否则查询全部数据)")
    public ResultData<PageDataVO<User>> getUsers(UserQueryParam userQueryParam) {
        log.info("查询用户信息");
        return new ResultData<PageDataVO<User>>().OK().setObj(userService.queryUsersByCondition(userQueryParam));
    }

    @DeleteMapping
    @ApiOperation(value = "根据id删除用户信息")
    public ResultData<Boolean> removeTraceInfo(@RequestParam Integer id) {
        log.info("根据id删除用户信息, id: {}", id);
        boolean rs = userService.removeById(id);
        log.info("删除结果: {}", rs ? "删除成功" : "删除失败");
        return new ResultData<Boolean>().OK().setObj(rs).setResultIns(rs ? "删除成功" : "删除失败, 或者该条记录是否已经被删除?");
    }

    @PutMapping
    @ApiOperation(value = "修改用户信息记录")
    @ValidateAspect.ParamValidate()
    public ResultData<Boolean> updateTraceInfo(@ApiParam(hidden = true) HttpServletRequest request,
                                               @Valid UserUpdateParam userUpdateParam,
                                               @ApiParam(hidden = true) @SuppressWarnings("unused") BindingResult bindingResult) {

        //数据整理
        User tmpUser = new User();
        BeanUtils.copyProperties(userUpdateParam, tmpUser);
        User user = (User) request.getSession().getAttribute(CURRENT_USER);
        tmpUser.setMender(user != null ? user.getId().toString() : null)
                .setModified(LocalDateTime.now());
        //判断是否更改了密码
        if (!StringUtils.isEmpty(userUpdateParam.getPassword())){
            String salt = UUIDUtils.getCode();
            tmpUser.setSalt(salt)
                    .setPassword(MD5Util.encode(tmpUser.getPassword() + salt));
        }

        log.info("修改用户信息记录操作, 溯源信息: {}", tmpUser);

        //修改操作
        boolean rs = userService.updateById(tmpUser);

        //结果返回
        if (rs) {
            log.info("用户信息修改成功");
            return new ResultData<Boolean>()
                    .OK()
                    .setResultIns("用户信息修改成功")
                    .setObj(Boolean.TRUE);
        } else {
            log.info("用户信息修改失败");
            return new ResultData<Boolean>()
                    .FAILED()
                    .setResultIns("用户信息修改失败")
                    .setObj(Boolean.FALSE);
        }

    }

    /*=========================================华丽的分割线==============================================*/
    /*=========================================以下为认证相关的接口==============================================*/

    /**
     * 访问禁止需要授权提示信息
     *
     * @return 访问禁止需要授权提示信息
     */
    @ApiOperation(value = "访问禁止需要授权提示信息", hidden = true)
    @RequestMapping("/authentication/require")
    public ResultData requireAuthentication() {
        log.info("需要登录");
        return new ResultData<Boolean>()
                .FAILED()
                .setResultIns("需要登录")
                .setObj(Boolean.FALSE);
    }

    /**
     * 登录失败提示信息
     *
     * @return 登录失败提示信息
     */
    @ApiOperation(value = "登录失败提示信息", hidden = true)
    @RequestMapping("/loginError")
    public ResultData loginError() {
        log.info("登录失败");
        return new ResultData<Boolean>()
                .FAILED()
                .setResultIns("登录失败, 请检查用户名或密码")
                .setObj(Boolean.FALSE);
    }

    /**
     * 登录成功信息响应
     *
     * @param request 当前请求对象
     * @return 登录成功信息响应
     */
    @RequestMapping("/loginSuccess")
    @ApiOperation(value = "登录成功信息响应", hidden = true)
    public ResultData<UserVO> loginSuccess(HttpServletRequest request, HttpServletResponse response) {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        request.getSession().setAttribute(CURRENT_USER, principal);
        //登录成功后, 给前端响应用户基本信息
        UserVO userVO = null;
        if (principal instanceof User) {
            userVO = dozerMapper.map(principal, UserVO.class);
        }
        response.setHeader("test", "111");
        System.out.println(response.getHeaderNames());
        log.info("登录成功");
        return new ResultData<UserVO>()
                .OK()
                .setResultIns("登录成功")
                .setObj(userVO);
    }


}

